import Promise from 'promise';
import validator from 'validator';
import utility from 'utility';
import uuid from 'node-uuid';
import config from '../config';
import * as mail from '../common/mail';
import * as tools from '../common/tools';
import * as authMiddleWare from '../middlewares/auth';
import * as ResultMsg from '../constrants/ResultMsg';
import { errorJson, successJson, errorRender, successRender } from '../common/response';
import { checkId, checkName, checkDoc } from '../common/check';
import { UserProxy } from '../proxy';

export {
  tryAuth,
  accesstoken,
  signup,
  signin,
  signout,
  activeAccount,
  createSearchPassword,
  authSearchPassword,
  updateResetPassword,
};

const notJump = [
  '/active_account', // active page
  '/reset_pass',     // reset password page, avoid to reset twice
  '/signup',         // regist page
  '/search_pass',    // serch pass page
];

// 非登录用户也可通过
function tryAuth(req, res, next) {
  const appId = res.locals.appId;
  if (req.session && req.session.user) {
    authMiddleWare.gen_session(req.session.user, res);
    const active = (req.session.user && req.session.user.active) || false;
    const user = req.session.user;
    successJson(req, res, { data: { user, active } });
  } else {
    successJson(req, res, { message: 'try auth error.' });
  }


  // let accessToken = String(req.body.accessToken || '');
  // accessToken = validator.trim(accessToken);

  // UserProxy.getUserByAccessToken(accessToken)
  //   .then(user => {
  //     if (user) {
  //       if (user.is_block) return res.json({success: false, message: '您的账户被禁用'})
  //       req.user = user
  //       req.session.user = user
  //       next();
  //     } else {
  //       return res.json({success: false, message: '登录失效，请重新登录'})
  //     }
  //   })
  //   .catch(err => next(err))
}

function accesstoken(req, res, next) {
  authMiddleWare.gen_session(req.user, res);
  const active = (req.user && req.user.active) || false;
  const user = req.user;
  successJson(req, res, { data: { user, active } });
}

async function signup(req, res, next) {
  const appId = res.locals.appId;
  const loginname = validator.trim(req.body.loginname).toLowerCase();
  const email = validator.trim(req.body.email).toLowerCase();
  const password = validator.trim(req.body.password) || '';
  const rePassword = validator.trim(req.body.rePassword) || '';

  // 验证信息的正确性
  if ([loginname, password, rePassword, email].some(item => item === '')) {
    return errorJson(req, res, { err: '信息不完整' });
  }
  if (loginname.length < 5) {
    return errorJson(req, res, { err: '用户名至少需要5个字符' });
  }
  if (!tools.validateId(loginname)) {
    return errorJson(req, res, { err: '用户名不合法' });
  }
  if (!validator.isEmail(email)) {
    return errorJson(req, res, { err: '邮箱不合法' });
  }
  if (password !== rePassword) {
    return errorJson(req, res, { err: '两次密码输入不一致' });
  }

  const active = false;
  const avatar = UserProxy.makeGravatar(email);
  // END 验证信息的正确性

  try {
    const doc = await UserProxy.findOne(appId, { $or: [{ loginname }, { email }] });
    if (doc) return errorJson(req, res, { err: ResultMsg.ACCOUNT_EXIST });

    const passwordHash = tools.bhash(password);
    const newDoc = await UserProxy.create(appId, { loginname, passwordHash, email, avatar, active });

    mail.sendActiveMail(email, utility.md5(email + passwordHash + config.session_secret), loginname);
    successJson(req, res, { data: { user: doc, active: false }, msg: `欢迎加入${config.name}！我们已给您的注册邮箱发送了一封邮件, 请点击里面的链接来激活您的帐号。` });
  } catch (err) {
    next(err);
  }
}

/**
 * Handle user login.
 *
 * @param {HttpRequest} req
 * @param {HttpResponse} res
 * @param {Function} next
 */
async function signin(req, res, next) {
  const appId = res.locals.appId;
  const loginname = validator.trim(req.body.loginname || '').toLowerCase();
  const password = validator.trim(req.body.password || '');

  if (!loginname || !password) {
    return errorJson(req, res, { err: '信息不完整' });
  }

  let conditions;
  if (loginname.indexOf('@') !== -1) {
    conditions = { email: loginname };
  } else {
    conditions = { loginname };
  }

  try {
    const doc = await UserProxy.findFullOne(appId, conditions);
    if (!doc) return errorJson(req, res, { err: '账号不存在' });

    const isOk = tools.bcompare(password, doc.pass);
    if (!isOk) return errorJson(req, res, { err: '密码错误' });

    doc.pass = '';

    if (!doc.active) {
      mail.sendActiveMail(doc.email, utility.md5(doc.email + doc.pass + config.session_secret), doc.loginname);
      successJson(req, res, { data: { user: doc, active: false }, message: `此帐号还没有被激活，激活链接已发送到 ${doc.email} 邮箱，请查收。` });
      return;
    }

    authMiddleWare.gen_session(doc, res);
    // check at some page just jump to home page
    let refer = req.session._loginReferer || '/';
    for (let i = 0, len = notJump.length; i !== len; ++i) {
      if (refer.indexOf(notJump[i]) >= 0) {
        refer = '/';
        break;
      }
    }

    successJson(req, res, { data: { user: doc, active: true } });
  } catch (err) {
    next();
  }
}

// sign out
function signout(req, res, next) {
  req.session.destroy();
  res.clearCookie(config.auth_cookie_name, { path: '/' });
  successJson(req, res, { msg: '登出成功' });
}

async function activeAccount(req, res, next) {
  const appId = res.locals.appId;
  const key = validator.trim(req.query.key || '');
  const loginname = validator.trim(req.query.name || '');

  try {
    const doc = await UserProxy.findFullOne(appId, { loginname });
    if (!doc) return errorRender(req, res, { err: ResultMsg.DATA_NOT_FOUND });

    const key2 = utility.md5(doc.email + doc.pass + config.session_secret);
    if (key !== key2) {
      return errorRender(req, res, { err: '信息有误，帐号无法被激活' });
    }

    if (doc.active) {
      return errorRender(req, res, { err: '帐号已经是激活状态' });
    }

    const data = {
      active: true,
    };

    await UserProxy.update(appId, doc._id, data);
    successRender(req, res, { msg: '帐号已被激活，请登录' });
  } catch (err) {
    next(err);
  }
}

async function createSearchPassword(req, res, next) {
  const appId = res.locals.appId;
  const email = validator.trim(req.body.email).toLowerCase();
  if (!validator.isEmail(email)) {
    return errorJson(req, res, { err: '邮箱不合法' });
  }

  try {
    const doc = await UserProxy.findFullOne(appId, {email});
    if (!doc) return errorJson(req, res, { err: ResultMsg.DATA_NOT_FOUND });

    const data = {
      retrieveKey: uuid.v4(),
      retrieveTime: new Date().getTime(),
    };

    await UserProxy.update(appId, doc._id, data);
    mail.sendResetPassMail(email, data.retrieveKey, doc.loginname);
    successJson(req, res, { msg: '我们已给您填写的电子邮箱发送了一封邮件，请在24小时内点击里面的链接来重置密码。' });
  } catch (err) {
    next(err);
  }
}

async function authSearchPassword(req, res, next) {
  const appId = res.locals.appId;
  const key = validator.trim(req.body.key || '');
  const loginname = validator.trim(req.body.loginname || '');
  const newPassword = validator.trim(req.body.newPassword || '');
  const reNewPassword = validator.trim(req.body.reNewPassword || '');

  if (newPassword !== reNewPassword) {
    return errorJson(req, res, { err: '输入的密码不一致' });
  }

  try {
    const doc = await UserProxy.findFullOne(appId, { loginname, retrieveKey: key });
    if (!doc) {
      return errorJson(req, res, { err: `找不到用户${loginname}` });
    }

    const now = new Date().getTime();
    const oneDay = 1000 * 60 * 60 * 24;

    if (!doc.retrieveTime || now - doc.retrieveTime > oneDay) {
      return errorJson(req, res, { err: '该链接已过期，请重新申请' });
    }

    const data = {
      retrieveTime: '',
      retrieveKey: '',
      pass: tools.bhash(newPassword),
      active: true
    };

    await UserProxy.update(appId, doc._id, data);
    successJson(req, res, { msg: ResultMsg.UPDATE_SUCCESS });
  } catch (err) {
    next(err);
  }
}

async function updateResetPassword(req, res, next) {
  const appId = res.locals.appId;
  const userId = req.session.user._id;
  const oldPassword = validator.trim(req.body.oldPassword) || '';
  const newPassword = validator.trim(req.body.newPassword) || '';

  if (oldPassword === newPassword) {
    return errorJson(req, res, { err: '新密码和老密码一致' });
  }

  try {
    const doc = await UserProxy.findFullOne(appId, { _id: userId });
    const isOk = tools.bcompare(oldPassword, doc.pass);
    if (!isOk) {
      return errorJson(req, res, { err: '老密码不对' });
    }

    const data = {
      pass: tools.bhash(newPassword),
      active: true
    };

    await UserProxy.update(appId, userId, data);
    successJson(req, res, { msg: ResultMsg.UPDATE_SUCCESS });
  } catch (err) {
    next(err);
  }
}

